#include "Vector3f.h"

using namespace XYF;

Vector3f::Vector3f(Real x, Real y, Real z) : m_x(x), m_y(y), m_z(z)
{
}

Vector3f Vector3f::operator*(Real t) const
{
    return {m_x * t, m_y * t, m_z * t};
}

Vector3f Vector3f::operator/(Real t) const
{
    assert(fabs(t) > FLT_MIN);
    return {m_x / t, m_y / t, m_z / t};
}

Vector3f Vector3f::operator-(const Vector3f &v) const
{
    return {m_x - v.x(), m_y - v.y(), m_z - v.z()};
}

Vector3f Vector3f::operator+(const Vector3f &v) const
{
    return {m_x + v.x(), m_y + v.y(), m_z + v.z()};
}

bool Vector3f::operator==(const Vector3f &v) const
{
    if (length(v - *this) < 1e-6)
        return true;
    return false;
}

Real Vector3f::x() const
{
    return m_x;
}

Real Vector3f::y() const
{
    return m_y;
}

Real Vector3f::z() const
{
    return m_z;
}

Real &Vector3f::rx()
{
    return m_x;
}

Real &Vector3f::ry()
{
    return m_y;
}

Real &Vector3f::rz()
{
    return m_z;
}

Real Vector3f::r() const
{
    return m_x;
}

Real Vector3f::g() const
{
    return m_y;
}

Real Vector3f::b() const
{
    return m_z;
}

Real &Vector3f::rr()
{
    return m_x;
}

Real &Vector3f::rg()
{
    return m_y;
}

Real &Vector3f::rb()
{
    return m_z;
}

Vector3f XYF::linear(Vector3f p1, Vector3f p2, Real t)
{
    return {p1.x() * (1 - t) + p2.x() * t,
            p1.y() * (1 - t) + p2.y() * t,
            p1.z() * (1 - t) + p2.z() * t};
}

Vector3f XYF::cross(Vector3f v1, Vector3f v2)
{
    return {v1.y() * v2.z() - v1.z() * v2.y(),
            -v1.x() * v2.z() + v1.z() * v2.x(),
            v1.x() * v2.y() - v1.y() * v2.x()};
}

Vector3f XYF::normalize(Vector3f p)
{
    Real len = length(p);
    assert(len > FLT_MIN);
    return p / len;
}

Real XYF::det(Vector3f v1, Vector3f v2, Vector3f v3)
{
    return dot(cross(v1, v2), v3);
}

Real XYF::length(Vector3f p)
{
    return sqrt(p.x() * p.x() + p.y() * p.y() + p.z() * p.z());
}

Real XYF::distance(Vector3f p1, Vector3f p2)
{
    return sqrt(pow(p1.x() - p2.x(), 2) + pow(p1.y() - p2.y(), 2) + pow(p1.z() - p2.z(), 2));
}

Real XYF::dot(Vector3f v1, Vector3f v2)
{
    return v1.x() * v2.x() + v1.y() * v2.y() + v1.z() * v2.z();
}

bool XYF::onLine(Vector3f p1, Vector3f p2, Vector3f p3)
{
    Vector3f vec1 = p1 - p2;
    Vector3f vec2 = p1 - p3;

    // 叉积足够大，则认为不共线
    if (length(cross(vec1, vec2)) > FLT_MIN)
        return false;
    return true;
}

bool XYF::onFace(Vector3f p1, Vector3f p2, Vector3f p3, Vector3f p4)
{
    Vector3f vec1 = p1 - p2;
    Vector3f vec2 = p1 - p3;
    Vector3f vec3 = p1 - p4;

    // 计算三个向量的行列式，如果足够大，则认为不共面
    if (fabs(det(vec1, vec2, vec3)) > FLT_MIN)
        return false;
    return true;
}
